package lfp.engine.arma;

import lfp.engine.utils.TimeSeries;
import lfp.engine.IForecastModel;


/**
 * Created by IntelliJ IDEA.
 * User: Guo
 * Date: Dec 30, 2005
 * Time: 4:07:54 PM
 * To change this template use File | Settings | File Templates.
 */
public class ArmaModel extends Arma implements IForecastModel {
    private int daysPeriod = 7;

    public int getDaysPeriod() {
        return daysPeriod;
    }

    public void setDaysPeriod(int daysPeriod) {
        this.daysPeriod = daysPeriod;
    }


    public double [] forecast(double [] series,int series_Period ,int forelength) {
        // according some model to forecast wanted series
        TimeSeries pData = new TimeSeries();
        pData.SetSeries(series.length, series);

        TimeSeries pControl = null;
        TimeSeries pControlFore = null;

        TimeSeries pFore = new TimeSeries();
        pFore.SetSeries(forelength);

        boolean bSuccess = predictWithDifferent(pData, pControl, pControlFore, pFore, series_Period);

        if (bSuccess)
            return pFore.getData();
        else
            return null;
    }

    public boolean predictWithDifferent(TimeSeries s1, TimeSeries c1, TimeSeries c2, TimeSeries r1, int season) {
        if (season <= 0) return predictIt(s1, c1, c2, r1);
        //

//        s1.Different(season*daysPeriod,1);
        s1.Different(season, 1);
        s1.Different(1,1);

        //
        TimeSeries s11 = new TimeSeries();
        TimeSeries c11 = new TimeSeries();
        int len = s1.m_nLen - season-1;
//        int len = s1.m_nLen - season*(daysPeriod +1)-1;

        s1.GetSubSeries(season+1, 1, s11, len);
        if (c1 != null && c1.m_nLen > 0) c1.GetSubSeries(season, 1, c11, len);
        boolean bSuccess = predictIt(s11, c11, c2, r1);
        //
        TimeSeries y = new TimeSeries();
        y.SetSeries(s1.m_nLen + r1.m_nLen);

        for (int i = 0; i < s1.m_nLen; i++)
            y.m_pSeries[i] = s1.m_pSeries[i];
        for (int i = 0; i < r1.m_nLen; i++)
            y.m_pSeries[i + s1.m_nLen] = r1.m_pSeries[i];
        y.Intergral(1,1);
        y.Intergral(season,1);
//        y.Intergral(season*daysPeriod, 1);



        for (int i = 0; i < s1.m_nLen; i++)
            s1.m_pSeries[i] = y.m_pSeries[i];
        for (int i = 0; i < r1.m_nLen; i++)
            r1.m_pSeries[i] = y.m_pSeries[s1.m_nLen + i];

        return bSuccess;
    }

    boolean predictIt(TimeSeries pS1, TimeSeries pC1, TimeSeries pC2, TimeSeries pR1) {
        if (pC1 != null && pC1.m_nLen == 0) pC1 = null;
        if (pC2 != null && pC2.m_nLen == 0) pC2 = null;
        //
        int pMax = 1000;//pS1.m_nLen/10;
        String methodName = "AR";
        Arma arma = new Arma();
        if (methodName.equals("AR")) arma.SetModel(AForecastModel._Model_Ar);
        else if (methodName.equals("ARLONG")) arma.SetModel(AForecastModel._Model_LongAr);
        else if (methodName.equals("ARX")) arma.SetModel(AForecastModel._Model_Arx);
        else if (methodName.equals("ARMA")) arma.SetModel(AForecastModel._Model_Arma);

        if (!arma.Forecast(pS1, pC1, pC2, pR1, pMax)) return false;
        return true;
    }
}
